package com.ybear.ybutils.utils.handler

import android.os.Build
import android.os.Looper
import android.os.Message
import android.util.Printer
import androidx.annotation.RequiresApi
import androidx.core.util.Consumer
import java.util.concurrent.Callable

internal class HandlerX : Handler {
    private val mImpl: HandlerImpl

    constructor(looper: Looper, call: Callback) {
        mImpl = HandlerImpl( looper, call )
    }
    constructor(looper: Looper, call: android.os.Handler.Callback) {
        mImpl = HandlerImpl( looper, call )
    }
    constructor(call: android.os.Handler.Callback) {
        mImpl = HandlerImpl( call )
    }
    constructor(looper: Looper) {
        mImpl = HandlerImpl( looper )
    }
    constructor(call: Callback) {
        mImpl = HandlerImpl( call )
    }

    override val looper: Looper get() = mImpl.looper
    override val osHandler: android.os.Handler get() = mImpl
    override val handler: Handler get() = this
    override fun postCheck(looper: Looper?, r: Runnable): Boolean {
        looper ?: Looper.myLooper()?.apply {
            return if( this == Looper.getMainLooper() ) {
                r.run()
                true
            }else {
                post( r )
            }
        }
        return false
    }

    override fun postCheck(r: Runnable): Boolean { return postCheck( null, r ) }

    override fun <T> postAsync(executeCall: Callable<T>, resultCall: Consumer<T>,
                               postResult: Boolean): Boolean {
        return mImpl.postAsync( executeCall, resultCall, postResult)
    }

    override fun <T> postAsync(executeCall: Consumer<Consumer<T>>, resultCall: Consumer<T>,
                               postResult: Boolean): Boolean {
        return mImpl.postAsync( executeCall, resultCall, postResult)
    }

    override fun <T> postDelayedAsync(executeCall: Callable<T>, resultCall: Consumer<T>,
                                      postResult: Boolean, delayMillis: Long): Boolean {
        return mImpl.postDelayedAsync( executeCall, resultCall, postResult, delayMillis )
    }

    override fun <T> postDelayedAsync(executeCall: Consumer<Consumer<T>>, resultCall: Consumer<T>, 
                                      postResult: Boolean, delayMillis: Long): Boolean {
        return mImpl.postDelayedAsync( executeCall, resultCall, postResult, delayMillis )
    }

    override fun <T> postAsync(executeCall: Callable<T>, resultCall: Consumer<T>,
                               postResult: Boolean, delayMillis: Long): Boolean {
        return mImpl.postAsync( executeCall, resultCall, postResult, delayMillis )
    }

    override fun <T> postAsync(executeCall: Consumer<Consumer<T>>, resultCall: Consumer<T>,
                               postResult: Boolean, delayMillis: Long): Boolean {
        return mImpl.postAsync( executeCall, resultCall, postResult, delayMillis )
    }

    override fun <T> postAsync(executeCall: Callable<T>, resultCall: Consumer<T>): Boolean {
        return mImpl.postAsync( executeCall, resultCall)
    }

    override fun <T> postAsync(executeCall: Consumer<Consumer<T>>,
                               resultCall: Consumer<T>): Boolean {
        return mImpl.postAsync( executeCall, resultCall)
    }

    override fun <T> postDelayedAsync(executeCall: Callable<T>, resultCall: Consumer<T>,
                                      delayMillis: Long): Boolean {
        return mImpl.postDelayedAsync( executeCall, resultCall, delayMillis )
    }

    override fun <T> postDelayedAsync(executeCall: Consumer<Consumer<T>>, resultCall: Consumer<T>,
                                      delayMillis: Long): Boolean {
        return mImpl.postDelayedAsync( executeCall, resultCall, delayMillis )
    }

    override fun <T> postAsync(executeCall: Callable<T>, resultCall: Consumer<T>,
                               delayMillis: Long): Boolean {
        return mImpl.postAsync( executeCall, resultCall, delayMillis )
    }

    override fun <T> postAsync(executeCall: Consumer<Consumer<T>>, resultCall: Consumer<T>,
                               delayMillis: Long): Boolean {
        return mImpl.postAsync( executeCall, resultCall, delayMillis )
    }

    override fun postAsync(executeCall: Runnable): Boolean {
        return mImpl.postAsync(executeCall)
    }

    override fun postDelayedAsync(executeCall: Runnable, delayMillis: Long): Boolean {
        return mImpl.postDelayedAsync( executeCall, delayMillis )
    }

    override fun postAsync(executeCall: Runnable, delayMillis: Long): Boolean {
        return mImpl.postAsync( executeCall, delayMillis )
    }

    override fun post(r: Runnable): Boolean {
        return mImpl.post( r )
    }

    override fun post(r: Runnable, delayMillis: Long): Boolean {
        return if ( delayMillis > 0 ) mImpl.postDelayed( r, delayMillis ) else mImpl.post( r )
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    override fun post(r: Runnable, token: Any?, delayMillis: Long): Boolean {
        return mImpl.postDelayed( r, token, delayMillis )
    }

    override fun postDelayed(r: Runnable, delayMillis: Long): Boolean {
        return mImpl.postDelayed( r, delayMillis )
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    override fun postDelayed(r: Runnable, token: Any?, delayMillis: Long): Boolean {
        return mImpl.postDelayed( r, token, delayMillis )
    }

    override fun postAtFrontOfQueue(r: Runnable): Boolean {
        return mImpl.postAtFrontOfQueue( r )
    }

    override fun postAtTime(r: Runnable, uptimeMillis: Long): Boolean {
        return mImpl.postAtTime( r, uptimeMillis )
    }

    override fun postAtTime(r: Runnable, token: Any?, uptimeMillis: Long): Boolean {
        return mImpl.postAtTime( r, token, uptimeMillis )
    }

    override fun sendMessage(msg: Message): Boolean {
        return mImpl.sendMessage( msg )
    }

    override fun sendEmptyMessage(what: Int): Boolean {
        return mImpl.sendEmptyMessage( what )
    }

    override fun sendEmptyMessageDelayed(what: Int, delayMillis: Long): Boolean {
        return mImpl.sendEmptyMessageDelayed( what, delayMillis )
    }

    override fun sendEmptyMessageAtTime(what: Int, uptimeMillis: Long): Boolean {
        return mImpl.sendEmptyMessageAtTime( what, uptimeMillis)
    }

    override fun sendMessageDelayed(msg: Message, delayMillis: Long): Boolean {
        return mImpl.sendMessageDelayed( msg, delayMillis )
    }

    override fun sendMessageAtTime(msg: Message, uptimeMillis: Long): Boolean {
        return mImpl.sendMessageAtTime( msg, uptimeMillis)
    }

    override fun sendMessageAtFrontOfQueue(msg: Message): Boolean {
        return mImpl.sendMessageAtFrontOfQueue( msg )
    }

    override fun hasMessages(what: Int): Boolean {
        return mImpl.hasMessages( what )
    }

    override fun hasMessages(what: Int, `object`: Any?): Boolean {
        return mImpl.hasMessages( what, `object` )
    }

    override fun removeMessages(what: Int) {
        mImpl.removeMessages( what )
    }

    override fun removeMessages(what: Int, `object`: Any?) {
        mImpl.removeMessages( what, `object`)
    }

    @RequiresApi(api = Build.VERSION_CODES.Q)
    override fun hasCallbacks(r: Runnable): Boolean {
        return mImpl.hasCallbacks( r )
    }

    override fun removeCallbacks(r: Runnable) {
        mImpl.removeCallbacks( r )
    }

    override fun removeCallbacks(r: Runnable, token: Any?) {
        mImpl.removeCallbacks( r, token )
    }

    override fun removeCallbacksAndMessages(token: Any?) {
        mImpl.removeCallbacksAndMessages( token )
    }

    override fun obtainMessage(): Message {
        return mImpl.obtainMessage()
    }

    override fun obtainMessage(what: Int): Message {
        return mImpl.obtainMessage( what )
    }

    override fun obtainMessage(what: Int, obj: Any?): Message {
        return mImpl.obtainMessage( what, obj )
    }

    override fun obtainMessage(what: Int, arg1: Int, arg2: Int): Message {
        return mImpl.obtainMessage( what, arg1, arg2 )
    }

    override fun obtainMessage(what: Int, arg1: Int, arg2: Int, obj: Any?): Message {
        return mImpl.obtainMessage( what, arg1, arg2, obj )
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    override fun createAsyncForOs(looper: Looper): android.os.Handler {
        return android.os.Handler.createAsync( looper )
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    override fun createAsyncForOs(looper: Looper,
                                  callback: android.os.Handler.Callback): android.os.Handler {
        return android.os.Handler.createAsync( looper, callback )
    }

    override fun dump(pw: Printer, prefix: String) { mImpl.dump( pw, prefix ) }
}